package xyz.xtt.admin.exception;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import xyz.xtt.common.exception.NftException;
import xyz.xtt.common.response.ApiResult;
import xyz.xtt.admin.constants.ErrorMessage;

import java.util.List;

/**
 * 全局异常处理器
 *
 * @author huqibo
 * @version 1.0 &#064;date 2021/10/18 16:00
 */

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
	private static final String STR = ";";

	/**
	 * 处理所有接口数据验证异常
	 *
	 * @param e       MethodArgumentNotValidException 数据验证异常
	 * @param request HttpServletRequest 请求对象
	 * @return ApiResult<String> 异常响应
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseBody
	public ApiResult<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
		List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
		String errorMsg = formatAllErrorMessages(allErrors);
		String url = request.getRequestURI();
		log.error("GlobalExceptionHandler handleMethodArgumentNotValidException url:{} ex: {}", url, errorMsg, e);
		return ApiResult.failure(ErrorMessage.ARGUMENT_NOT_VALID.code(), errorMsg);

	}

	/**
	 * 拦截未知的运行时异常
	 *
	 * @param e       RuntimeException 运行时异常
	 * @param request HttpServletRequest 请求对象
	 * @return ApiResult<String> 异常响应
	 */
	@ExceptionHandler(ChainException.class)
	@ResponseBody
	public ApiResult<Void> handleRuntimeException(ChainException e, HttpServletRequest request) {
		String url = request.getRequestURI();
		log.error("requset ChainException: {}", url, e);
		return ApiResult.failure(e);
	}

	/**
	 * 异常消息拼接
	 *
	 * @param errors List<ObjectError> 异常殚表
	 * @return String 异常消息
	 */
	private String formatAllErrorMessages(List<ObjectError> errors) {
		StringBuffer errorMsg = new StringBuffer();
		errors.forEach(error -> errorMsg.append(error.getDefaultMessage()).append(STR));
		return errorMsg.toString();
	}

	/**
	 * 拦截未知的运行时异常
	 *
	 * @param e       RuntimeException 运行时异常
	 * @param request HttpServletRequest 请求对象
	 * @return ApiResult<String> 异常响应
	 */
	@ExceptionHandler(RuntimeException.class)
	@ResponseBody
	public ApiResult<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
		String url = request.getRequestURI();
		log.error("requset RuntimeException: {}", url, e);
		return ApiResult.failure(ErrorMessage.UNKNOWN_ERROR.code(), ErrorMessage.UNKNOWN_ERROR.message());
	}

	/**
	 * 拦截未知的运行时异常
	 *
	 * @param e       RuntimeException 运行时异常
	 * @param request HttpServletRequest 请求对象
	 * @return ApiResult<String> 异常响应
	 */
	@ExceptionHandler(NftException.class)
	@ResponseBody
	public ApiResult<Void> handleRuntimeException(NftException e, HttpServletRequest request) {
		String url = request.getRequestURI();
		log.error("requset NftException: {}", url, e);
		return ApiResult.failure(e);
	}

	/**
	 * 系统异常
	 */
	@ExceptionHandler(Exception.class)
	@ResponseBody
	public ApiResult<Void> handleException(Exception e, HttpServletRequest request) {
		String url = request.getRequestURI();
		log.error("rquestUrl: {}, exception.", url, e);
		return ApiResult.failure(ErrorMessage.UNKNOWN_ERROR.code(), ErrorMessage.UNKNOWN_ERROR.message());
	}
}
